#include "server/dbm_server.h"
#include "dbm_conf.h"
#include "server/dbm_socket.h"
#include "lsdb/dbm_lsdb_handle.h"
#include "pdb/dbm_policy_handler.h"
#include <stdio.h>
#include "timer/timer.h"
#include "lsdb/dbm_lsdb_manager.h"
#include <pthread.h>
pthread_mutex_t mutex_timer=PTHREAD_MUTEX_INITIALIZER;
int timer_snapshoot = -1;
//int timer_save_snap = 0;


int dbm_start(){
	dbm_status = DBM_STATUS_CLOSED;
	if(dbm_connect()!=0){
		//printf("dbm start faild!error dbm_connect()\n");
		DEBUG(INFO,"DBM start failed!");
		return -1;
	}
	dbm_status = DBM_STATUS_LOGGING;
	/*if(dbm_install()!=0){
		//printf("dbm install faild!\n");
		DEBUG(INFO,"DBM install failed!");
		dbm_status = DBM_STATUS_OFFLINE;
		//return -1;
		return 0;//for testing
	}*/
	dbm_status = DBM_STATUS_WORKING;
	dbm_add_event(save_lsdb_to_file,NULL,10); //30s save lsdb to file
	//timer_save_snap = dbm_add_event(dbm_save_snapshoot,NULL,1);//1s save the lsdb
	DEBUG(INFO,"DBM is started!");
	pthread_t pid;
	pthread_create(&pid,NULL,(void*)dbm_deamon,NULL);
	sleep(100);
	//dbm_deamon();
}
int dbm_init(){
	self_module = DBM;
	//init the lsdb,lidb,pdb
	//init the other
}
int dbm_install(){
	//fill the reg packet
	//dbm_send_data();
	int ret = -1;
	int tried = 0;
	while(tried<1){
		char* reg_content = NULL;
		int packet_len = sizeof(Packet_header);
		Packet_headerp reg_packet = (Packet_headerp)malloc(packet_len);
		reg_packet->sour_module = self_module;
		reg_packet->dest_module = BM;
		reg_packet->action = LOGIN;
		reg_packet->length = NULL;
		//memcpy(reg_packet+sizeof(Packet_header),mydata,sizeof(mydata));
		struct packet pkt;
		pkt.sockfd = global_bm_sock;
		pkt.type = LOGIN;
		pkt.len = packet_len;
		pkt.head = reg_packet;
		pkt.body = NULL;

		//DEBUG(INFO,"Packet:%s",pkt.body);

		dbm_send_packet(&pkt);
		tried++;
		//dbm_send(global_bm_sock,reg_packet);
	}
	return ret;
}

int dbm_add_event(dbm_event call_event,void* args,long time){
	return set_timer(time,call_event,args,0);
}

int dbm_deamon(){
	while(1){
		dbm_get_data();
		//sleep(1);
	}
}
int dbm_get_data(){
	struct packet* pkt;
	//DEBUG(INFO,"debug user");
	pkt = dbm_recv_packet();
	if(pkt == NULL){return -1;}
	Packet_headerp p_header = (Packet_headerp)(pkt->head);
	int des,src,action,length;
	des = p_header->dest_module;
	src = p_header->sour_module;
	action = p_header->action;
	length = p_header->length;
	if(des != DBM)
	{
		DEBUG(INFO,"wrong packet received,throw it away");
		return -1;
	}
	//DEBUG(INFO,"Data received:%s",pkt->body);
	switch(action){
		case LOGIN:DEBUG(INFO,"Register into the bm successfuly");break;
		case LSDB:dbm_lsdb_handle(pkt->body,length);
		//dbm_add_event(send_lsdb_snap_shoot,NULL,10);
		if(timer_snapshoot == -1){
			pthread_mutex_lock(&mutex_timer);
			timer_snapshoot = set_timer(5,send_lsdb_snap_shoot,NULL,0); //only there is no new lsa,then send pkt
			pthread_mutex_unlock(&mutex_timer);
		}
		else
		{
			pthread_mutex_lock(&mutex_timer);
			printf("timer update!\n");
			update_timer(timer_snapshoot);
			printf("error is here\n");
			pthread_mutex_unlock(&mutex_timer);
		}
			DEBUG(INFO,"receive a lsdb packet");break;
		case LIDB://dbm_lidb_handle(pkt->body,length);
		DEBUG(INFO,"receive a lidb packet");break;
		case PDB: dbm_pdb_handle(pkt->body,length);
		DEBUG(INFO,"receive a pdb packet");break;
		default:DEBUG(INFO,"receive a packet dont know");break;
	}
	//dbm_receive();
	//get the header,decide which should be use. handle_type
	//switch(handle_type):
	//case '':dbm_lsdb_handle();
}
int dbm_send_data(char* data,int length,int type){
	if(length<=0){
		DEBUG(ERROR,"send data's length is wrong");
		return -1;
	}
	char* data_content = data;
	int packet_len = sizeof(Packet_header)+length;
	Packet_headerp packet = (Packet_headerp)malloc(packet_len);
	packet->sour_module = self_module;
	packet->dest_module = BM;
	packet->action = type;
	packet->length = length;
	memcpy(packet+sizeof(Packet_header),data_content,length);

	struct packet pkt;
	pkt.sockfd = global_bm_sock;
	pkt.type = packet->action;
	pkt.len = packet->length;
	pkt.head = packet;
	pkt.body = packet+sizeof(Packet_header);

	//DEBUG(INFO,"Packet:%s",pkt.body);

	dbm_send_packet(&pkt);
	//dbm_send();
}

int dbm_lidb_handle();
int dbm_pdb_handle();
